﻿
using DongFangGuoKai.WMSPlatform.Commn.ApiResultModule;
using DongFangGuoKai.WMSPlatform.Commn.ExtendModule;
using DongFangGuoKai.WMSPlatform.WebApi.Collection;
using Newtonsoft.Json;
using System.Net.WebSockets;
using System.Text;
namespace DongFangGuoKai.WMSPlatform.WebApi.Middleware
{
    /// <summary>
    /// WebSocket连接的入口点
    /// </summary>
    public class WebsocketHandlerMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<WebsocketHandlerMiddleware> _logger;


        public WebsocketHandlerMiddleware(RequestDelegate next, ILogger<WebsocketHandlerMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            //协议标识符是ws
            if (context.Request.Path != "/ws")
            {
                await _next.Invoke(context);
                return;
            }

            //仅当网页执行new WebSocket("ws://localhost:5000/ws")时，后台会执行此逻辑            
            if (!context.WebSockets.IsWebSocketRequest)
            {
                context.Response.StatusCode = 400;
                return;
            }
            //获取WebSocket连接
            //“握手”完成
            WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
            WebSocketClient webSocketClient = new WebSocketClient()
            {
                Id = Guid.NewGuid().ToString(),
                WebSocket = webSocket
            };
            try
            {
                await Echo(webSocketClient);

            }
            catch (Exception ex)
            {

                _logger.LogError(ex.Message);
            }


        }

        private static async Task Echo(WebSocketClient webSocketClient)
        {

            WebSocketCollection.AddSocketClient(webSocketClient);

            var buffer = new byte[1024 * 4];
            WebSocketReceiveResult? result = await webSocketClient.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

            //处理接受到的消息

            while (!result.CloseStatus.HasValue)
            {
                if (result.MessageType == WebSocketMessageType.Close)
                {
                    throw new WebSocketException(WebSocketError.ConnectionClosedPrematurely, result.CloseStatusDescription);
                }
                var text = Encoding.UTF8.GetString(buffer.AsSpan(0, result.Count));
                var msg = JsonConvert.DeserializeObject<WebSocketClientModel>(text);
                msg.SendClientId = webSocketClient.Id;
                await Handle(msg);
                result = await webSocketClient.WebSocket.ReceiveAsync(
                    new ArraySegment<byte>(buffer), CancellationToken.None);
            }
            WebSocketCollection.RemoveSocket(webSocketClient);
            await webSocketClient.WebSocket.CloseAsync(
                result.CloseStatus.Value,
                result.CloseStatusDescription,
                CancellationToken.None);

        }

        private static async Task Handle(WebSocketClientModel webSocketClientModel)
        {
            ApiBaseResult result;
            var webSocket = WebSocketCollection.Get(webSocketClientModel.SendClientId);
            switch (webSocketClientModel.Action)
            {
                //加入房间
                case "join":
                    webSocket.RoomNo = webSocketClientModel.RoomNo;
                    result = new ApiBaseResult()
                    {
                        Msg = $"加入成功",
                        Code = 200,
                        Success = true

                    };
                    await webSocket.WebSocket.SendAsync(Encoding.UTF8.GetBytes(result.ToJson()), WebSocketMessageType.Text, true, CancellationToken.None);

                    return;
                case "send_to_room":
                    if (string.IsNullOrEmpty(webSocket.RoomNo))
                    {
                        break;
                    }
                    var clients = WebSocketCollection.GetRoomClients(webSocket.RoomNo);
                    clients.ForEach(async c =>
                    {
                        await c.WebSocket.SendAsync(Encoding.UTF8.GetBytes(webSocket.Id + "加入了房间"), WebSocketMessageType.Text, true, CancellationToken.None);
                    });
                    return;
                //断连
                case "leave":

                    result = new ApiDataResult<object>
                    {
                        Msg = $"主动段连，时间：{DateTime.Now}",
                        Code = 200,
                        Success = true,
                        Data = new
                        {
                            Id = webSocket.Id
                        }
                    };

                    if (webSocket != null)
                    {
                        WebSocketCollection.RemoveSocket(webSocket);
                    }
                    await webSocket.WebSocket.SendAsync(Encoding.UTF8.GetBytes(result.ToJson()), WebSocketMessageType.Text, true, CancellationToken.None);

                    await webSocket.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);


                    return;
                default:

                    result = new ApiBaseResult()
                    {
                        Code = 400,
                        Msg = "约定俗成失败",
                        Success = false

                    };
                    await webSocket.WebSocket.SendAsync(Encoding.UTF8.GetBytes(result.ToJson()), WebSocketMessageType.Text, true, CancellationToken.None);
                    return;
            }
        }



    }
}
